﻿using G19Glower.Shared;
using System;
using System.Drawing;
using System.Xml.Linq;

namespace G19Glower.Glowies
{
    [GlowerInfo("Linear Glower", "Changes colour the more you type.")]
    internal class LinearGlowerOverlord : IGlower, ISettings
    {
        private IServicesProvider mServiceProvider;
        private XElement mSettingsStore;
        private LinearGlower mGlower;
        private LinearGlowerSettings mSettings;

        private XAttribute mIdleColourAttribute;
        private XAttribute mGlowColourAttribute;
        private XAttribute mFadeoutTimeAttribute;
        private XAttribute mFreezeTimeAttribute;
        private XAttribute mGlowGrowthAttribute;

        #region IGlower Members

        void IGlower.Initialize(IServicesProvider serviceProvider)
        {
            mServiceProvider = serviceProvider;

            var keyboardService = mServiceProvider.GetService<IKeyboardListener>();
            var glowController = mServiceProvider.GetService<IGlowController>();

            mGlower = new LinearGlower(glowController, keyboardService);

            var settingsManager = mServiceProvider.GetService<ISettingsManager>();
            settingsManager.RegisterSettings(this);
        }

        void IGlower.Start()
        {
            mGlower.Start();
        }

        void IGlower.Stop()
        {
            mGlower.Stop();
        }

        bool IGlower.IsRunning
        {
            get { return mGlower.IsRunning; }
        }

        #endregion

        #region Settings Methods

        private void UpdateSettingsFromGlower()
        {
            // Create and sync settings to current glower
            mSettings.IdleColour = new System.Windows.Media.Color()
            {
                A = 255,
                R = mGlower.IdleColour.R,
                G = mGlower.IdleColour.G,
                B = mGlower.IdleColour.B
            };
            mSettings.GlowColour = new System.Windows.Media.Color()
            {
                A = 255,
                R = mGlower.GlowColour.R,
                G = mGlower.GlowColour.G,
                B = mGlower.GlowColour.B
            };

            mSettings.FadeoutTime = mGlower.FadeoutTime.TotalMilliseconds;
            mSettings.FreezeTime = mGlower.FreezeTime.TotalMilliseconds;
            mSettings.GlowGrowth = mGlower.IncrementValue * 100;
        }

        private void UpdateGlowerFromSettings()
        {
            mGlower.IdleColour =
                    Color.FromArgb(mSettings.IdleColour.R,
                                   mSettings.IdleColour.G,
                                   mSettings.IdleColour.B);

            mGlower.GlowColour =
                Color.FromArgb(mSettings.GlowColour.R,
                               mSettings.GlowColour.G,
                               mSettings.GlowColour.B);

            mGlower.FadeoutTime = TimeSpan.FromMilliseconds(mSettings.FadeoutTime);
            mGlower.FreezeTime = TimeSpan.FromMilliseconds(mSettings.FreezeTime);
            mGlower.IncrementValue = mSettings.GlowGrowth / 100.0;
        }

        private void UpdateStoreFromGlower()
        {
            mIdleColourAttribute.Value = mGlower.IdleColour.ToArgb().ToString();
            mGlowColourAttribute.Value = mGlower.GlowColour.ToArgb().ToString();
            mFadeoutTimeAttribute.Value = mGlower.FadeoutTime.TotalMilliseconds.ToString();
            mFreezeTimeAttribute.Value = mGlower.FreezeTime.TotalMilliseconds.ToString();
            mGlowGrowthAttribute.Value = ((int)(mGlower.IncrementValue * 100)).ToString();
        }

        private void UpdateGlowerFromStore()
        {
            try
            {
                mGlower.IdleColour = Color.FromArgb(int.Parse(mIdleColourAttribute.Value));
                mGlower.GlowColour = Color.FromArgb(int.Parse(mGlowColourAttribute.Value));
                mGlower.FadeoutTime = TimeSpan.FromMilliseconds(int.Parse(mFadeoutTimeAttribute.Value));
                mGlower.FreezeTime = TimeSpan.FromMilliseconds(int.Parse(mFreezeTimeAttribute.Value));
                mGlower.IncrementValue = int.Parse(mGlowGrowthAttribute.Value) / 100.0;
            }
            catch
            {
                // Whatever
                this.UpdateStoreFromGlower();
            }
        }

        #endregion

        #region ISettings Members

        event EventHandler ISettings.SettingsUIValueChanged
        {
            add { this.mSettings.ValueChanged += value; }
            remove { this.mSettings.ValueChanged -= value; }
        }

        void ISettings.Initialize(System.Xml.Linq.XElement settingsElement)
        {
            mSettings = new LinearGlowerSettings();
            mSettingsStore = settingsElement;

            mIdleColourAttribute = this.GetAttribute(mSettingsStore, "IdleColour");
            mGlowColourAttribute = this.GetAttribute(mSettingsStore, "GlowColour");
            mFadeoutTimeAttribute = this.GetAttribute(mSettingsStore, "FadeoutTime");
            mFreezeTimeAttribute = this.GetAttribute(mSettingsStore, "FreezeTime");
            mGlowGrowthAttribute = this.GetAttribute(mSettingsStore, "GlowGrowth");

            this.UpdateGlowerFromStore();
        }                                                    

        void ISettings.ApplySettings()
        {
            this.UpdateGlowerFromSettings();
            this.UpdateStoreFromGlower();
        }

        string ISettings.SettingsTitle
        {
            get { return "Linear Glower"; }
        }

        System.Windows.FrameworkElement ISettings.SettingsUI
        {
            get 
            {
                this.UpdateSettingsFromGlower();
                return mSettings;
            }
        }

        #endregion

        #region Helpers

        private XAttribute GetAttribute(XElement parent, XName name)
        {
            var attribute = parent.Attribute(name);
            if (attribute == null)
            {
                attribute = new XAttribute(name, "");
                parent.Add(attribute);
            }

            return attribute;
        }


        #endregion
    }
}
